package cn.bugstack.domain.strategy.service.armory;

import cn.bugstack.domain.strategy.model.entity.StrategyAwardEntity;
import cn.bugstack.domain.strategy.repository.IStrategyRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.security.SecureRandom;
import java.util.*;

/**
 * @author Lee
 * @date 2025/5/14
 * @description 策略装配库（兵工厂），负责初始化策略计算
 */
@Service
@Slf4j
public class StrategyArmory implements IStrategyArmory {

    @Resource
    private IStrategyRepository strategyRepository;

    @Override
    public void assembleLotteryStrategy(Long strategyId) {
        // 1.查询策略配置信息：从策略仓库中查询指定策略ID的所有奖项配置信息
        List<StrategyAwardEntity> strategyAwardEntityList = strategyRepository.queryStrategyAwardList(strategyId);
        //2.获取最小概率值：使用Stream API找出所有奖项中的最小概率值
        //如果找不到，默认返回0
        BigDecimal minAwardRate = strategyAwardEntityList
                .stream()
                .map(StrategyAwardEntity::getAwardRate)
                .min(BigDecimal::compareTo)
                .orElse(BigDecimal.ZERO);
        // 检查最小概率是否为0
        if (minAwardRate.compareTo(BigDecimal.ZERO) == 0) {
            throw new IllegalArgumentException("最小概率值不能为0");
        }
        //3.获取概率值总和：计算所有奖项概率的总和
        //使用reduce方法进行累加
        BigDecimal totalAwardRate = strategyAwardEntityList
                .stream()
                .map(StrategyAwardEntity::getAwardRate)
                //从0开始累加
                .reduce(BigDecimal.ZERO,BigDecimal::add);
        //4.计算概率范围：用总概率除以最小概率，得到概率范围
        //保留4位小数，向下舍入
        // 用 1 % 0.0001 获取概率范围，百分位、千分位、万分位
        BigDecimal rateRange = totalAwardRate.divide(minAwardRate, 4, BigDecimal.ROUND_DOWN);// divide（除数，小数位数，舍入模式）
        //构建概率查找表：
        // 根据每个奖项的概率，计算其在查找表中应占的比例
        //使用向上取整确保每个奖项至少有一个位置
        //将奖项ID填充到查找表中
        ArrayList<Integer> strategyAwardSearchRateTables = new ArrayList<>(rateRange.intValue());
        for (StrategyAwardEntity strategyAward : strategyAwardEntityList) {
            Integer awardId = strategyAward.getAwardId();
            BigDecimal awardRate = strategyAward.getAwardRate();
            //计算出每个概率值需要存放到查找表的数量，循环填充
            for (int i = 0; i < rateRange.multiply(awardRate).setScale(0, RoundingMode.CEILING).intValue(); i++) {
                strategyAwardSearchRateTables.add(awardId);
            }
        }
        //6. 乱序 打乱数组顺序，不会生成新数组
        Collections.shuffle(strategyAwardSearchRateTables);

        //7.构建映射表：将打乱后的查找表转换为键值对映射
        //键为索引，值为奖项ID
        HashMap<Integer, Integer> shuffleStrategyAwardSearchRateTables = new HashMap<>();
        for (int i = 0; i < strategyAwardSearchRateTables.size(); i++) {
            shuffleStrategyAwardSearchRateTables.put(i, strategyAwardSearchRateTables.get(i));
        }
        //8.存储到redis
        strategyRepository.storeStrategyAwardSearchRateTables(strategyId,BigDecimal.valueOf(shuffleStrategyAwardSearchRateTables.size()),shuffleStrategyAwardSearchRateTables);
    }

    @Override
    public Integer getRandomAwardId(Long strategyId) {
        int rateRange = strategyRepository.getRateRange(strategyId);
        return strategyRepository.getStrateAwardAssemble(strategyId,new SecureRandom().nextInt(rateRange));

    }

}
